package repository

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"mts/trans_srv/internal/domain"
	"mts/trans_srv/internal/repository/dao"
	"strconv"
)

type ElementRepository interface {
	FindElementByID(ctx context.Context, id string) (domain.Element, error)
	FindAll(ctx context.Context) ([]domain.Element, error)
	List(ctx context.Context, page, pageSize int) ([]domain.Element, error)
	DeleteById(ctx context.Context, id string) error
	EditById(ctx context.Context, id string, element domain.Element) error
	Insert(ctx context.Context, element domain.Element) error
	Save(ctx context.Context, info domain.CreateElementAndTranslationInfo) error
	CheckExistByElementName(ctx context.Context, name string) (bool, error)
	GetListCount(ctx context.Context) (int, error)
}

type GormElementRepository struct {
	dao dao.ElementDao
}

func (g GormElementRepository) GetListCount(ctx context.Context) (int, error) {
	return g.dao.GetListCount(ctx)
}

func (g GormElementRepository) Save(ctx context.Context, info domain.CreateElementAndTranslationInfo) error {
	// 创建 Element 对象
	ele := &dao.Element{
		Name:        info.Name,
		Type:        info.Type,
		Description: info.Description,
	}

	// 检查 Element 是否存在
	existingElement := &dao.Element{}
	if info.ID != "" {
		id, err := strconv.Atoi(info.ID)
		if err != nil {
			return err
		}
		existingElement, err = g.dao.FindElementByID(ctx, strconv.Itoa(id))
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			g.dao.Save(ctx, ele, existingElement, info.Translations)
			return nil
		}
		if err != nil {
			return err
		}
	}
	g.dao.Save(ctx, ele, existingElement, info.Translations)
	return nil
}

func (g GormElementRepository) List(ctx context.Context, page, pageSize int) ([]domain.Element, error) {
	elements, err := g.dao.List(ctx, page, pageSize)
	if err != nil {
		return nil, err
	}
	var elementsDomain []domain.Element
	for _, v := range elements {
		elementsDomain = append(elementsDomain, g.entityToDomain(v))
	}
	return elementsDomain, err
}

func NewElementRepository(dao dao.ElementDao) ElementRepository {
	return &GormElementRepository{dao: dao}
}

func (g GormElementRepository) FindElementByID(ctx context.Context, id string) (domain.Element, error) {
	element, err := g.dao.FindElementByID(ctx, id)
	if err != nil {
		return domain.Element{}, err
	}
	ele := g.entityToDomain(element)
	return ele, nil
}

func (g GormElementRepository) FindAll(ctx context.Context) ([]domain.Element, error) {
	elements, err := g.dao.FindAll(ctx)
	if err != nil {
		return nil, err
	}
	var elementsDomain []domain.Element
	for _, v := range elements {
		elementsDomain = append(elementsDomain, g.entityToDomain(v))
	}
	return elementsDomain, err
}

func (g GormElementRepository) DeleteById(ctx context.Context, id string) error {
	err := g.dao.DeleteById(ctx, id)
	if err != nil {
		return err
	}
	return nil
}

func (g GormElementRepository) EditById(ctx context.Context, id string, element domain.Element) error {
	//TODO implement me
	panic("implement me")
}

func (g GormElementRepository) Insert(ctx context.Context, element domain.Element) error {
	entity := g.toEntity(element)
	err := g.dao.Insert(ctx, &entity)
	if err != nil {
		return err
	}
	return nil
}

func (g GormElementRepository) CheckExistByElementName(ctx context.Context, name string) (bool, error) {
	return g.dao.CheckExistByElementName(ctx, name)
}
func (g GormElementRepository) entityToDomain(ele *dao.Element) domain.Element {
	return domain.Element{
		ID:          strconv.Itoa(ele.ID),
		Name:        ele.Name,
		Type:        ele.Type,
		Description: ele.Description,
	}
}
func (g GormElementRepository) toEntity(l domain.Element) dao.Element {
	id, _ := strconv.Atoi(l.ID)
	return dao.Element{
		ID:          id,
		Name:        l.Name,
		Type:        l.Type,
		Description: l.Description,
	}
}
